<template>
  <div>
    <el-form class="m7-form" ref="dirTreeForm" :model="dirTreeForm" :rules="rule" label-position="top" size="mini" @submit.native.prevent>
      <el-form-item :label="`${nameType}名称`" prop="label">
        <el-input v-model="dirTreeForm.label" :placeholder="`请输入${nameType}名称`" size="mini"></el-input>
      </el-form-item>
      <el-form-item label="目录权限" prop="accessList" v-if="isKnowledge">
        <div class="visiblePersonnelTransfer">
          <tree-transfer
            height="400px"
            mode="transfer"
            node_key="_id"
            pid="parentId"
            :from_data="selectOrigin"
            :to_data="selectResult"
            @add-btn="add"
            @remove-btn="remove"
            :defaultProps="{ label: 'name' }"
            :title="['未选项', '已选项']"
            placeholder="输入关键字进行过滤"
            :high-light="true"
            filter
            openAll
          >
            <div slot="content-right" slot-scope="{ node, data }" class="right">
              <el-tooltip effect="dark" :content="node.label" placement="top">
                <span class="label">{{ node.label }}</span>
              </el-tooltip>
              <div v-if="!data.isRoot" class="iconBox">
                <span :class="{'V7_iconfont': true, 'selColor': showList.includes(data._id), 'V7_iconV7tubiao_kejian-xuanzhong': showList.includes(data._id), 'V7_iconV7tubiao_kejian-weixuan': !showList.includes(data._id)}" @click.stop="toShow(node)"></span>
                <span :class="{'V7_iconfont': true, 'selColor': editList.includes(data._id), 'V7_iconV7tubiao_bianji-xuanzhong ': editList.includes(data._id), 'V7_iconV7tubiao_xianbianji': !editList.includes(data._id)}" @click.stop="toEdit(node)"></span>
              </div>
            </div>
          </tree-transfer>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import treeTransfer from 'el-tree-transfer'
import sideBar from '@/common/views/sideBar/index.vue'
import cloneDeep from 'lodash/cloneDeep'
const LABEL_LIST = ['座席', '部门', '技能组']
const temp = {
  label: '',
  level: '',
  parentId: '',
  type: '',
  _id: ''
}
@Component({
  name: 'addOrEditDirTree',
  components: { sideBar, treeTransfer }
})
export default class DirectoryTree extends Vue {
[x: string]: any
  @Prop({ default: () => '目录' }) private nameType: string | undefined
  @Prop() private indexRow?: any
  @Prop() private isEdit?: boolean
  @Prop(({ default: () => true })) private isKnowledge?: boolean
  private rule = {
    label: [{ required: true, trigger: 'blur', message: '请输入名称' }]
  }

  private resultTree = []

  private selectOrigin: any = []

  private selectResult = []

  private showList: any = []

  private editList: any = []

  public dirTreeForm = {
    label: '',
    level: '',
    parentId: '',
    type: '',
    _id: ''
  }

  @Watch('indexRow', { immediate: true })
  public setDirTreeData (data?: any) {
    if (data) {
      const { label, level, _id, type, parentId } = data
      this.dirTreeForm = {
        label: type === 'add' ? '' : label,
        level,
        parentId: type === 'add' ? _id : parentId, // 新增时父结点取当前结点id，编辑时需取parentId
        type,
        _id
      }
    } else {
      this.dirTreeForm = temp
    }
  }

  get transformData () {
    const { showList, editList } = this
    const [
      { children: agentList },
      departmentList,
      { children: skillGroupList }
    ] = this.selectOriginCopy
    const flattenList = this.treeFlatten(departmentList);
    return {
      showAgentIds: showList.filter(i => agentList.some(m => m._id === i)),
      editAgentIds: editList.filter(i => agentList.some(m => m._id === i)),
      showDepartmentIds: showList.filter(i => flattenList.some(m => m._id === i)),
      editDepartmentIds: editList.filter(i => flattenList.some(m => m._id === i)),
      showPeerIds: showList.filter(i => skillGroupList.some(m => m._id === i)),
      editPeerIds: editList.filter(i => skillGroupList.some(m => m._id === i))
    }
  }

  private async created () {
    const { departmentList, queueList, userList } = await this.getData()
    const cmpDepartment = departmentList.map((i: any) => ({ ...i, parentId: 2 }));
    this.deepSetRoot(cmpDepartment)
    this.selectOrigin = [
      userList.map((i: { agentName: any, status: string }) => ({ ...i, name: i.agentName, parentId: 1, disabled: i?.status !== 'enable' })),
      cmpDepartment,
      queueList.map((i: any) => ({ ...i, parentId: 3, disabled: i?.status !== 'enable' }))
    ].map((i, m) => ({
      name: LABEL_LIST[m],
      children: i,
      _id: m + 1,
      isRoot: true
    }))
    this.selectOriginCopy = cloneDeep(this.selectOrigin)
    if (!this.isEdit) {
      return
    }
    this.deepSet(this.indexRow)
  }

  public async getData () {
    const res = await this.$getCache('/base/action/general/cache/query', ['userList', 'departmentList', 'queueList'], false)
    return res
  }

  public treeFlatten (tree) {
    const res: any = []
    const each = (arr) => {
      if (!arr) {
        return
      }
      arr.forEach((i) => {
        res.push(i)
        if (i.children) {
          each(i.children)
        }
      })
    }
    each(tree.children)
    return res
  }

  public deepSet (row: any) {
    const selectResult: any = []
    const { showList, editList, agentList, departmentList, skillGroupList } = this.getListFromRow(row)
    const agentObj: any = {}
    const departmentObj: any = {}
    const skillGroupObj: any = {}
    const getResult = ({ obj }: any) => {
      if (agentList.includes(obj._id)) {
        if (this.isEmpty(agentObj)) {
          agentObj.name = LABEL_LIST[0]
          agentObj.children = [obj]
          agentObj._id = 1
          agentObj.isRoot = true
        } else {
          agentObj.children.push(obj)
        }
      } else if (skillGroupList.includes(obj._id)) {
        if (this.isEmpty(skillGroupObj)) {
          skillGroupObj.name = LABEL_LIST[2]
          skillGroupObj.children = [obj]
          skillGroupObj._id = 3
          skillGroupObj.isRoot = true
        } else {
          skillGroupObj.children.push(obj)
        }
      } else if (departmentList.includes(obj._id)) {
        const departmentNodes = this.selectOrigin.find(i => i._id === 2).children || []
        const nodeId = obj.rootId || obj._id;
        const indexRoot = departmentNodes.find(i => i?._id === nodeId);
        if (this.isEmpty(departmentObj)) {
          departmentObj.name = LABEL_LIST[1]
          departmentObj.children = [indexRoot]
          departmentObj._id = 2
          departmentObj.isRoot = true
        } else {
          if (departmentObj.children.every(i => i._id !== indexRoot._id)) {
            departmentObj.children.push(indexRoot)
          }
        }
      }
    }
    const eachSet = (list: any[]) => {
      list.forEach(i => {
        const hasShow = showList.includes(i._id)
        const hasEdit = editList.includes(i._id)
        if (hasShow) {
          this.showList.push(i._id)
          getResult({ obj: i })
        } else if (hasEdit) {
          this.editList.push(i._id)
          getResult({ obj: i })
        }
        eachSet(i?.children || [])
      })
    }
    eachSet(this.selectOriginCopy)
    if (!this.isEmpty(agentObj)) {
      selectResult.push(agentObj)
    }
    if (!this.isEmpty(departmentObj)) {
      selectResult.push(departmentObj)
    }
    if (!this.isEmpty(skillGroupObj)) {
      selectResult.push(skillGroupObj)
    }
    this.selectResult = selectResult
  }

  public deepSetRoot (list) {
    const deepSet = (arr, indexRootId) => {
      arr.forEach(i => {
        if (i) {
          i.rootId = indexRootId
        }
        if (i.children) {
          deepSet(i.children, indexRootId)
        }
      })
    }
    list.forEach(i => deepSet(i.children, i._id))
  }

  public isEmpty (obj: any) {
    return Object.keys(obj).length === 0
  }

  public getListFromRow (row: any) {
    const {
      showAgentIds,
      showDepartmentIds,
      showPeerIds,
      editAgentIds,
      editDepartmentIds,
      editPeerIds
    } = row
    return {
      agentList: [...showAgentIds, ...editAgentIds],
      departmentList: [...showDepartmentIds, ...editDepartmentIds],
      skillGroupList: [...showPeerIds, ...editPeerIds],
      showList: [
        ...showAgentIds,
        ...showDepartmentIds,
        ...showPeerIds
      ],
      editList: [
        ...editAgentIds,
        ...editDepartmentIds,
        ...editPeerIds
      ]
    }
  }

  public checkInclude (list: any, id: any) {
    return list.some((i: { _id: any }) => i._id === id)
  }

  public toShow (node: any) {
    if (!this.showList.includes(node.data._id)) {
      this.showList.push(node.data._id)
      this.editList = this.editList.filter((i: any) => i !== node.data._id)
    }
  }

  public toEdit (node: any) {
    if (!this.editList.includes(node.data._id)) {
      this.editList.push(node.data._id)
      this.showList = this.showList.filter((i: any) => i !== node.data._id)
    }
  }

  public add (_: any, __: any, { keys }) {
    this.showList.push(...keys.filter((i) => !this.showList.includes(i)))
  }

  public remove (_: any, __: any, { keys }) {
    this.showList = this.showList.filter((i: any) => !keys.includes(i))
    this.editList = this.editList.filter((i: any) => !keys.includes(i))
  }

  public init () {
    this.selectResult = []
    this.showList = []
    this.editList = []
  }

  public beforeDestroy () {
    this.init()
  }
}
</script>
<style lang="stylus" scoped>
  .visiblePersonnelTransfer
    margin-top 4px
    & >>> .wl-transfer .transfer-title
      font-size 12px
    & >>> .wl-transfer .transfer-main
      overflow hidden
    & >>> .wl-transfer .el-tree
      height calc(100% - 50px)
      // border 1px solid red
      overflow-y auto
    & >>> .custom-tree-node
      font-size 12px
      flex 1
  .right
    display flex
    justify-content space-between
    position relative
    flex 1
  .iconBox
    width 42px
    display flex
    justify-content space-between
    margin-right 12px
    position absolute
    right 0
    >>> .V7_iconfont
      color #B3B9C7
      cursor pointer
  .label
    width 50px
    overflow hidden
    text-overflow ellipsis
  .selColor
    color #008BEE !important
</style>
